﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lucene.Net.Search;
using System.Collections;
using Lucene.Net.Documents;
using Lucene.Net.Highlight;

namespace ObjectSearch
{
    public class PagedSearchResults<T> : LuceneObjectSearchBase, IPagedSearchResults<T>
    {
        public Hits LuceneHits { get; private set; }
        public Query LuceneQuery { get; private set; }

        private int _PageNumber;
        private int _ItemsPerPage;

        private IList<ISearchResultItem<T>> _Results;

        public PagedSearchResults(Hits hits, Query query, int pageNumber, int itemsPerPage,
            IndexSettings settings, Configuration.Configuration configuration)
            : base(settings, configuration)
        {
            this.LuceneHits = hits;
            this.LuceneQuery = query;

            _ItemsPerPage = itemsPerPage;
            _PageNumber = pageNumber;

            GetResults(pageNumber, itemsPerPage);
        }

        private void GetResults(int pageNumber, int itemsPerPage)
        {
            _Results = new List<ISearchResultItem<T>>();
            
            int start = pageNumber * itemsPerPage;
            
            //is negative number just return.
            if (start < 0)
                return;
            
            for (int i = 0; i < itemsPerPage; i++)
            {
                int documnetNumber = i + start;

                if (documnetNumber >= TotalResultItems)
                {
                    break;                                                    
                }

                Document doc = LuceneHits.Doc(documnetNumber);

                SearchResultItem<T> item = new SearchResultItem<T>(
                    doc, LuceneQuery, IndexSettings, Configuration);

                _Results.Add(item);
            }
        }

        #region IPagedSearchResults Members

        public int TotalPages
        {
            get
            {
                int totalPages = TotalResultItems / this._ItemsPerPage;
                return totalPages;
            }
        }

        public int TotalResultItems
        {
            get { return LuceneHits.Length(); }
        }

        public int CurrentPageNumber
        {
            get { return _PageNumber;; }
        }

        public int NumberOfItems
        {
            get { return Results.Count; }
        }

        public IList<ISearchResultItem<T>> Results
        {
            get { return _Results; }
        }

        public IPagedSearchResults<T> GetNextPage()
        {
            return GetPage(CurrentPageNumber + 1);
        }

        public IPagedSearchResults<T> GetPreviousPage()
        {
            return GetPage(CurrentPageNumber - 1);
        }

        public IPagedSearchResults<T> GetPage(int pageNumber)
        {
            IPagedSearchResults<T> page = new PagedSearchResults<T>(
                LuceneHits, LuceneQuery, pageNumber, _ItemsPerPage, IndexSettings, Configuration);

            if (page.NumberOfItems == 0)
                return null;
            else
                return page;
        }

        #endregion

        #region IEnumerable<SearchResultItem> Members

        public IEnumerator<ISearchResultItem<T>> GetEnumerator()
        {
            return this.Results.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.Results.GetEnumerator();
        }

        #endregion
    }
}
